package com.omicrondev.flightops;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

import java.util.ListIterator;

/**
 * Created by gdean on 7/29/13.
 */
public class LoadingGraph extends View {
    private Paint mPaint, mLdgPaint, mZfPaint;
    private RectF mBounds;
    private float mZfWeight = 3094;
    private float mToWeight = 3094;
    private float mToArm = 86.4f;
    private float mLdgWeight = 3094;
    private float mLdgArm = 86.4f;
    private AcType mAcType = null;

    private float mXAxisStart, mPlotWidth, mXAxisRange, mXOffset;
    private float mYBottom, mYAxisStart, mPlotHeight, mYAxisRange, mYOffset;

    public LoadingGraph(Context context, AttributeSet attrs) {
        super(context, attrs);

        setId(R.id.loadingGraph);

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setARGB(255,0,0,0);
        mPaint.setStrokeWidth(2);

        mLdgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mLdgPaint.setStyle(Paint.Style.FILL);
        mLdgPaint.setARGB(255,27,178,224);
        mLdgPaint.setStrokeWidth(0);

        mZfPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mZfPaint.setStyle(Paint.Style.FILL);
        mZfPaint.setARGB(255,224,27,217);
        mZfPaint.setStrokeWidth(0);

        mXOffset = 20;
        mYOffset = 20;

        mXAxisStart = 0;
        mXAxisRange = 0;

        mYAxisStart = 0;
        mYAxisRange = 0;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        mBounds = new RectF(0, 0, w, h);

        mPlotWidth = w - (2 * mXOffset);
        mYBottom = h - mYOffset;
        mPlotHeight = h - (2 * mYOffset);
    }

    private float scaleX(float x) {
        return (((x - mXAxisStart) * (mPlotWidth / mXAxisRange)) + mXOffset);
    }

    private float scaleY(float y) {
        return (mYBottom - (((y - mYAxisStart) * (mPlotHeight / mYAxisRange)) + mYOffset));
    }

    private void DrawScaledLine(float x1, float y1, float x2, float y2, Canvas canvas, Paint paint) {
        canvas.drawLine(scaleX(x1), scaleY(y1), scaleX(x2), scaleY(y2), paint);
    }

    private void DrawScaledMarker(float x, float y, Canvas canvas) {
        canvas.drawCircle(scaleX(x), scaleY(y), 5, mPaint);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (mAcType == null)
            return;

        updatePlotRange();

        ListIterator<CGLimit> itr = mAcType.mFwdCG.listIterator();
        CGLimit lineStart = itr.next();
        CGLimit fwdPoint = null;
        while (itr.hasNext()) {
            fwdPoint = itr.next();
            DrawScaledLine((float)lineStart.mArm, lineStart.mWeight, (float)fwdPoint.mArm, fwdPoint.mWeight, canvas, mPaint);
            lineStart = fwdPoint;
        }

        itr = mAcType.mAftCG.listIterator();
        lineStart = itr.next();
        CGLimit rearPoint = null;
        while (itr.hasNext()) {
            rearPoint = itr.next();
            DrawScaledLine((float)lineStart.mArm, lineStart.mWeight, (float)rearPoint.mArm, rearPoint.mWeight, canvas, mPaint);
            lineStart = rearPoint;
        }

        if (fwdPoint != null && rearPoint != null)
            DrawScaledLine((float)fwdPoint.mArm, fwdPoint.mWeight, (float)rearPoint.mArm, rearPoint.mWeight, canvas, mPaint);

        double fwdLimit = mAcType.getFwdLimit(mAcType.mLdgLimit);
        double aftLimit = mAcType.getAftLimit(mAcType.mLdgLimit);
        DrawScaledLine((float)fwdLimit, mAcType.mLdgLimit, (float)aftLimit, mAcType.mLdgLimit, canvas, mLdgPaint);

        fwdLimit = mAcType.getFwdLimit(mAcType.mZfLimit);
        aftLimit = mAcType.getAftLimit(mAcType.mZfLimit);
        DrawScaledLine((float)fwdLimit, mAcType.mZfLimit, (float)aftLimit, mAcType.mZfLimit, canvas, mZfPaint);

        DrawScaledMarker(mToArm, mToWeight, canvas);
        DrawScaledMarker(mLdgArm, mLdgWeight, canvas);
    }

    public void setZF(float weight) {
        mZfWeight = weight;

        invalidate();
    }

    public void setTO(float weight, float arm) {
        mToWeight = weight;
        mToArm = arm;

        invalidate();
    }

    public void setLdg(float weight, float arm) {
        mLdgWeight = weight;
        mLdgArm = arm;

        invalidate();
    }

    public void setAcType(AcType acType) {
        mAcType = acType;
    }

    protected void updatePlotRange() {
        if (mAcType == null)
            return;

        CGLimit point;
        int minWeight = Integer.MAX_VALUE, maxWeight = 0;
        double minArm = Double.MAX_VALUE, maxArm = 0;

        ListIterator<CGLimit> itr = mAcType.mFwdCG.listIterator();
        while (itr.hasNext()) {
            point = itr.next();
            if (point.mWeight > maxWeight)
                maxWeight = point.mWeight;
            if (point.mWeight < minWeight)
                minWeight = point.mWeight;
            if (point.mArm > maxArm)
                maxArm = point.mArm;
            if (point.mArm < minArm)
                minArm = point.mArm;
        }

        itr = mAcType.mAftCG.listIterator();
        while (itr.hasNext()) {
            point = itr.next();
            if (point.mWeight > maxWeight)
                maxWeight = point.mWeight;
            if (point.mWeight < minWeight)
                minWeight = point.mWeight;
            if (point.mArm > maxArm)
                maxArm = point.mArm;
            if (point.mArm < minArm)
                minArm = point.mArm;
        }

        float armScale = (float)((maxArm - minArm) * .3);
        mXAxisStart = (float)(Math.floor(minArm - armScale));
        float xAxisEnd = (float)(Math.ceil(maxArm + armScale));
        mXAxisRange = xAxisEnd - mXAxisStart;

        mYAxisStart = minWeight;
        mYAxisRange = (float)(100 * Math.ceil(((maxWeight - minWeight) * 1.1) / 100));
    }
}
